package com.mochat.mochat.controller.wxpay;

import com.alibaba.druid.util.Base64;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.mochat.mochat.common.annotion.LoginToken;
import com.mochat.mochat.common.util.HttpClientUtil;
import com.mochat.mochat.common.util.JsonUtils;
import com.mochat.mochat.common.util.QRCodeUtil;
import com.mochat.mochat.common.util.wxpay.WXPay;
import com.mochat.mochat.common.util.wxpay.WXPayConfig;
import com.mochat.mochat.common.util.wxpay.WXPayConfigServer;
import com.mochat.mochat.common.util.wxpay.WXPayUtil;
import com.mochat.mochat.dao.entity.UserEntity;
import com.mochat.mochat.dao.entity.UserOrderEntity;
import com.mochat.mochat.model.wxpay.UnifiedOrderDTO;
import com.mochat.mochat.service.AccountService;
import com.mochat.mochat.service.impl.ISubSystemService;
import com.mochat.mochat.service.userOrder.IUserOrderService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.codec.digest.Md5Crypt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.MathContext;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.logging.SimpleFormatter;

/**
 * @author: JackLiu
 * @time: 2022/1/22 2:47 下午
 * @description 微信支付
 */
@Slf4j
@RestController
@RequestMapping("/wxpay")
public class WxPayController {

    @Autowired
    private IUserOrderService userOrderService;

    @Autowired
    private ISubSystemService subSystemService;

    private WXPayConfig config;

    /**
     * 作用：统一下单<br> 生成订单接口 native 用户扫码支付专用
     * 场景：公共号支付、扫码支付、APP支付
     * @param total_fee 向wxpay post的请求数据
     * @return API返回数据
     * @throws Exception
     */
    @GetMapping("/unifiedOrder")
    public Map<String, String> unifiedOrder(@RequestParam String order_desc, @RequestParam BigDecimal total_fee,
                                            @RequestParam String contact_id, @RequestParam Integer channel_code_id) throws Exception{
        WXPayConfigServer config = new WXPayConfigServer();
        WXPay wxpay = new WXPay(config);

        Map<String, String> data = new HashMap<String, String>();
        data.put("body", order_desc);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        String date = dateFormat.format(new Date());
        long l = System.currentTimeMillis();
        String outTradeNo = date + l;
        data.put("out_trade_no", outTradeNo);
        data.put("fee_type", "CNY");
        BigDecimal bigDecimal = new BigDecimal("100");
        Integer multiply = total_fee.multiply(bigDecimal).intValue();
        data.put("total_fee", multiply + "");
        data.put("spbill_create_ip", "182.98.171.82");
        data.put("notify_url", "https://api6.faracat.com/channelCode/wxPayNotify");
        data.put("trade_type", "NATIVE");  // 此处指定为扫码支付
        data.put("product_id", "11");

        Map<String, String> resp = wxpay.unifiedOrder(data);
        String old_code_url = resp.get("code_url");
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        QRCodeUtil.encode(old_code_url,byteArrayOutputStream);
        byte[] bytes = byteArrayOutputStream.toByteArray();
        String code_url = Base64.byteArrayToBase64(bytes);
        resp.put("code_url",code_url);
        System.out.println(resp);

        if("SUCCESS".equals(resp.get("return_code"))){
            UserOrderEntity userOrderEntity = new UserOrderEntity();
            userOrderEntity.setTotalFee(total_fee);
            userOrderEntity.setOrderDesc(order_desc);
            userOrderEntity.setOutTradeNo(outTradeNo);
            userOrderEntity.setExternalUserid(contact_id);
            userOrderEntity.setChannelCodeId(channel_code_id);
            userOrderEntity.setStatus("0");
            int userId = AccountService.getUserId();
            UserEntity userEntity = subSystemService.getById(userId);
            userOrderEntity.setTenantId(userEntity.getTenantId());
            userOrderService.save(userOrderEntity);
        }
        return resp;
    }

    /**
     * 作用：查询订单<br>
     * 场景：刷卡支付、公共号支付、扫码支付、APP支付
     * @param dto 向wxpay post的请求数据
     * @return API返回数据
     * @throws Exception
     */
    @GetMapping("orderQuery")
    public Map<String, String> orderQuery(@RequestBody UnifiedOrderDTO dto) throws Exception {

        WXPayConfigServer config = new WXPayConfigServer();
        WXPay wxpay = new WXPay(config);

        Map<String, String> data = new HashMap<String, String>();
        data.put("out_trade_no", dto.getOut_trade_no());

        Map<String, String> resp = wxpay.orderQuery(data);
        System.out.println(resp);
        return resp;

    }

    /**
     * jsapi支付成功后，支付回调处理
     * @param outTradeNo 统一下单时传的订单号
     * @return
     */
    @GetMapping("jsapiNotify")
    public Boolean jsapiNotify(String outTradeNo) throws Exception{
        UpdateWrapper<UserOrderEntity> queryWrapper = new UpdateWrapper<>();
        queryWrapper.eq("out_trade_no",outTradeNo);
        queryWrapper.set("status",1);
        boolean update = userOrderService.update(queryWrapper);
        return update;
    }

    /**
     * 作用：统一下单<br> 生成订单接口 jsapi公众号页面用户支付专用
     * 场景：公共号支付、扫码支付、APP支付
     * @param total_fee 向wxpay post的请求数据
     * @param contact_id 客户id
     * @return API返回数据
     * @throws Exception
     */
    @LoginToken
    @GetMapping("/unifiedOrder/jsapi")
    public Map<String, String> unifiedOrderJsapi(@RequestParam String order_desc, @RequestParam BigDecimal total_fee,
                                                 @RequestParam String contact_id, @RequestParam Integer channel_code_id,
                                                 @RequestParam String openid, @RequestParam Integer tenantId) throws Exception{
        WXPayConfigServer config = new WXPayConfigServer();
        WXPay wxpay = new WXPay(config);

        Map<String, String> data = new HashMap<String, String>();
        data.put("body", order_desc);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        String date = dateFormat.format(new Date());
        long l = System.currentTimeMillis();
        String outTradeNo = date + l;
        data.put("out_trade_no", outTradeNo);
        data.put("fee_type", "CNY");
        BigDecimal bigDecimal = new BigDecimal("100");
        Integer multiply = total_fee.multiply(bigDecimal).intValue();
        data.put("total_fee", multiply + "");
        data.put("spbill_create_ip", "182.98.171.82");
        data.put("notify_url", "https://api6.faracat.com/channelCode/wxPayNotify/jsapi");
        data.put("trade_type", "JSAPI");  // 此处指定为jsapi支付
        // openid是前端设置静默登陆拿到的用户openid
        data.put("openid", openid);

        Map<String, String> resp = wxpay.unifiedOrder(data);
        String timeStamp = String.valueOf(System.currentTimeMillis());
        resp.put("timeStamp",timeStamp);
        resp.put("package","prepay_id=" + resp.get("prepay_id"));
        resp.put("signType","MD5");
        resp.put("outTradeNo",outTradeNo);
        // 生成签名
        String nonceStr = WXPayUtil.generateNonceStr();
        resp.put("nonce_str",nonceStr);
        String param="appId=wx58826fc06869d4bf" +
                "&nonceStr=" + nonceStr + "&package=prepay_id=" + resp.get("prepay_id") +
                "&signType=" + "MD5" + "&timeStamp=" + timeStamp + "&key=" + "kR7ladftqXD8VUlda9md3nOcJWSgCXNJ";
        String paySign = DigestUtils.md5Hex(param).toUpperCase();
        resp.put("sign",paySign);
//        log.info("签名请求参数：" + param);
//        System.out.println("签名请求参数：" + param);
//        System.out.println("签名结果：" + paySign);
//        log.info("统一下单请求返回结果:" + JSONObject.toJSONString(resp));

        if("SUCCESS".equals(resp.get("return_code"))){
            UserOrderEntity userOrderEntity = new UserOrderEntity();
            userOrderEntity.setTotalFee(total_fee);
            userOrderEntity.setOrderDesc(order_desc);
            userOrderEntity.setOutTradeNo(outTradeNo);
            // 客户id
            userOrderEntity.setExternalUserid(contact_id);
            userOrderEntity.setChannelCodeId(channel_code_id);
            userOrderEntity.setStatus("0");
            userOrderEntity.setTenantId(tenantId);
            userOrderEntity.setOpenid(openid);
            userOrderService.save(userOrderEntity);
        }
        return resp;
    }

    /**
     * 作用：商家帮客户生成一个支付链接，本质是一个静默登陆的url链接，携带了接口需要的各种参数
     * 使用了喵喵云仓的appid
     * @throws Exception
     */
    @GetMapping("/create/paymentLink")
    public Map<String, String> createPaymentLink(@RequestParam String order_desc, @RequestParam BigDecimal total_fee,
                                                 @RequestParam String contact_id, @RequestParam Integer channel_code_id,
                                                 @RequestParam Integer tenantId) throws Exception{
        String old_code_url = "https://open.weixin.qq.com/connect/oauth2/authorize?" +
                "appid=wx58826fc06869d4bf&response_type=code&scope=snsapi_base&state=123";
        String uri = "https://admin6.faracat.com/user/order?order_desc=" + order_desc + "&total_fee=" + total_fee +
                "&contact_id=" + contact_id + "&channel_code_id=" + channel_code_id + "&tenantId=" + tenantId;
        String uriEncoder = URLEncoder.encode(uri);
        old_code_url = old_code_url + "&redirect_uri=" + uriEncoder + "#wechat_redirect";
        Map<String, String> resp = new HashMap<>();
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        QRCodeUtil.encode(old_code_url,byteArrayOutputStream);
        byte[] bytes = byteArrayOutputStream.toByteArray();
        String code_url = Base64.byteArrayToBase64(bytes);
        resp.put("code_url",code_url);
        resp.put("old_code_url",old_code_url);
        return resp;
    }

    /**
     * 作用：静默登陆后，传code获取openid
     * @throws Exception
     */
    @LoginToken
    @GetMapping("/getOpenId")
    public JSONObject getOpenId(@RequestParam String appid, @RequestParam String secret,
                            @RequestParam String grant_type, @RequestParam String code) throws Exception{
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="
        + appid + "&secret=" + secret + "&code=" + code + "&grant_type=" + grant_type;
        String s = HttpClientUtil.doPost(url, url);
        log.info("获取openid返回值：" + s);
        JSONObject jsonObject = JSONObject.parseObject(s);
        return jsonObject;
    }


}
